package model.item;

import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import model.map.GameMap;
import model.map.GameTile;
import model.mapping.ItemMapping;

public class ItemPopulator
{
	private static ItemPopulator populator = new ItemPopulator();
	private static ItemMapping itemMapping = ItemMapping.getItemMapping();
	
	private static final int HEAL_FREQ = 25, MAX_HEAL_RATE = 50, MAX_NUM_HEAL = 10,
							 DMG_FREQ = 25, MAX_DMG_RATE = 50, MAX_NUM_DMG= 10,
							 FOOD_FREQ = 12, MAX_FOOD_RATE = 50, MAX_NUM_FOOD = 10,
							 ORE_FREQ = 12, MAX_ORE_RATE = 50, MAX_NUM_ORE = 10,
							 ENERGY_FREQ = 12, MAX_ENERGY_RATE = 50, MAX_NUM_ENERGY = 10,
							 OBS_FREQ = 14, MAX_NUM_OBS = 10,
							 ITEM_FREQUENCY = 15;
	
	public static ItemPopulator getItemPopulator()
	{
		return populator;
	}
	
	public ItemPopulator()
	{
		
	}
	
	public void populate(GameMap map)
	{
		itemMapping.setMap(map);
		
		List<GameTile> bannedTiles = new LinkedList<GameTile>();
		
		while (map.hasNextStartingLocation())
			bannedTiles.add(map.getNextStartingLocation());
		map.resetStartingLocationPointer();
		
		addHealItems(map, bannedTiles);		
		addDamageItems(map, bannedTiles);
		addFoodItems(map, bannedTiles);
		addOreItems(map, bannedTiles);
		addEnergyItems(map, bannedTiles);
		addObstacles(map, bannedTiles);
	}

	private void addHealItems(GameMap map, List<GameTile> bannedTiles)
	{
		Random rnd = new Random();
		
		int numItems = 0;
		
		for (int i = 0; i < map.getMapLength() && numItems < MAX_NUM_HEAL; i++)
		{
			for (int j = 0; j < map.getMapHeight() && numItems < MAX_NUM_HEAL; j++)
			{
				GameTile tile = map.getTileAt(i, j);
				
				if (!bannedTiles.contains(tile))
				{
					int chance = rnd.nextInt(100);
					
					if (chance < ITEM_FREQUENCY)
					{
						chance = rnd.nextInt(100);
						
						if (chance < HEAL_FREQ)
						{
							int rate = rnd.nextInt(MAX_HEAL_RATE);
							
							itemMapping.addItem(tile, new HealItem(2, itemMapping, rate));
							numItems++;
							bannedTiles.add(tile);
						}
					}
				}
			}
		}
		
	}
	
	private void addDamageItems(GameMap map, List<GameTile> bannedTiles)
	{
		Random rnd = new Random();
		
		int numItems = 0;
		
		for (int i = 0; i < map.getMapLength() && numItems < MAX_NUM_DMG; i++)
		{
			for (int j = 0; j < map.getMapHeight() && numItems < MAX_NUM_DMG; j++)
			{
				GameTile tile = map.getTileAt(i, j);
				
				if (!bannedTiles.contains(tile))
				{
					int chance = rnd.nextInt(100);
					
					if (chance < ITEM_FREQUENCY)
					{
						chance = rnd.nextInt(100);
						
						if (chance < DMG_FREQ)
						{
							int rate = rnd.nextInt(MAX_DMG_RATE);
							
							itemMapping.addItem(tile, new DamageItem(2, itemMapping, rate));
							numItems++;
							bannedTiles.add(tile);
						}
					}
				}
			}
		}
		
	}
	
	private void addFoodItems(GameMap map, List<GameTile> bannedTiles)
	{
		Random rnd = new Random();
		
		int numItems = 0;
		
		for (int i = 0; i < map.getMapLength() && numItems < MAX_NUM_FOOD; i++)
		{
			for (int j = 0; j < map.getMapHeight() && numItems < MAX_NUM_FOOD; j++)
			{
				GameTile tile = map.getTileAt(i, j);
				
				if (!bannedTiles.contains(tile))
				{
					int chance = rnd.nextInt(100);
					
					if (chance < ITEM_FREQUENCY)
					{
						chance = rnd.nextInt(100);
						
						if (chance < FOOD_FREQ)
						{
							int rate = rnd.nextInt(MAX_FOOD_RATE);
							
							itemMapping.addItem(tile, new FoodItem(itemMapping, rate));
							numItems++;
							bannedTiles.add(tile);
						}
					}
				}
			}
		}
		
	}
	
	private void addOreItems(GameMap map, List<GameTile> bannedTiles)
	{
		Random rnd = new Random();
		
		int numItems = 0;
		
		for (int i = 0; i < map.getMapLength() && numItems < MAX_NUM_ORE; i++)
		{
			for (int j = 0; j < map.getMapHeight() && numItems < MAX_NUM_ORE; j++)
			{
				GameTile tile = map.getTileAt(i, j);
				
				if (!bannedTiles.contains(tile))
				{
					int chance = rnd.nextInt(100);
					
					if (chance < ITEM_FREQUENCY)
					{
						chance = rnd.nextInt(100);
						
						if (chance < ORE_FREQ)
						{
							int rate = rnd.nextInt(MAX_ORE_RATE);
							
							itemMapping.addItem(tile, new OreItem(itemMapping, rate));
							numItems++;
							bannedTiles.add(tile);
						}
					}
				}
			}
		}
		
	}
	
	private void addEnergyItems(GameMap map, List<GameTile> bannedTiles)
	{
		Random rnd = new Random();
		
		int numItems = 0;
		
		for (int i = 0; i < map.getMapLength() && numItems < MAX_NUM_ENERGY; i++)
		{
			for (int j = 0; j < map.getMapHeight() && numItems < MAX_NUM_ENERGY; j++)
			{
				GameTile tile = map.getTileAt(i, j);
				
				if (!bannedTiles.contains(tile))
				{
					int chance = rnd.nextInt(100);
					
					if (chance < ITEM_FREQUENCY)
					{
						chance = rnd.nextInt(100);
						
						if (chance < ENERGY_FREQ)
						{
							int rate = rnd.nextInt(MAX_ENERGY_RATE);
							
							itemMapping.addItem(tile, new EnergyItem(itemMapping, rate));
							numItems++;
							bannedTiles.add(tile);
						}
					}
				}
			}
		}
		
	}
	
	private void addObstacles(GameMap map, List<GameTile> bannedTiles)
	{
		Random rnd = new Random();
		
		int numItems = 0;
		
		for (int i = 0; i < map.getMapLength() && numItems < MAX_NUM_OBS; i++)
		{
			for (int j = 0; j < map.getMapHeight() && numItems < MAX_NUM_OBS; j++)
			{
				GameTile tile = map.getTileAt(i, j);
				
				if (!bannedTiles.contains(tile))
				{
					int chance = rnd.nextInt(100);
					
					if (chance < ITEM_FREQUENCY)
					{
						chance = rnd.nextInt(100);
						
						if (chance < OBS_FREQ)
						{
							itemMapping.addObstacle(tile, new Obstacle("OBSTACLE"));
							numItems++;
							bannedTiles.add(tile);
						}
					}
				}
			}
		}
		
	}
}
